/**
 * Copyright (c) 2009  Collaborative Development Group, C.S. Dept., University of Bari
 *
 * All rights reserved. This program and the accompanying materials are made available under
 * the terms of the Eclipse Public License v1.0  which accompanies this distribution, and is 
 * available at http://www.eclipse.org/legal/epl-v10.html
 */
package it.uniba.di.cdg.penelope.ui.mvp;

import static it.uniba.di.cdg.penelope.util.ReflectionUtilities.*;

import java.lang.reflect.Field;

import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Button;

/**
 * 
 */
public class ActionWiringService implements IActionWiringService {
	/* (non-Javadoc)
	 * @see it.uniba.di.cdg.penelope.ui.mvp.IActionWiringService#wire(java.lang.Object, java.lang.Object)
	 */
	@Override
	public <V, P> void wire( V v, P presenter ) {
		Class<?> viewType = getUnproxiedType( v.getClass() );
		
		if (!(v instanceof IManagedView)) {
			throw new MVPWiringException( 
					String.format( "View %s does not implement %s", viewType, IManagedView.class )  );
		}
		
		IManagedView view = (IManagedView) v;
		

		Field[] annotatedFields = getAnnotatedFields( viewType, PresenterEvent.class );
		for (Field f : annotatedFields) {
			Object fieldValue = getProperty( view, f.getName() );
			
			if (fieldValue instanceof Button) {
				wireButton( (Button) fieldValue, view, f.getAnnotation( PresenterEvent.class ) );
			} else {
				throw new MVPWiringException( String.format( "Unsupported type %s for action wiring!", fieldValue.getClass() ) );
			}
			
		}
	}

	/**
	 * @param fieldValue
	 * @param annotation
	 */
	private void wireButton( Button fieldValue, final IManagedView view, final PresenterEvent annotation ) {
		fieldValue.addSelectionListener( new SelectionAdapter() {
			@Override public void widgetSelected( SelectionEvent e ) {
				try {
					view.fire( annotation.value().newInstance() );
				} catch (Throwable t) {
					new MVPWiringException( t );
				} 
			}
		});		
	}
}
